﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.IO;
namespace ACNetMusic
{
    class ServerController
    {
#region Attributes
        private ClientController clientCtrl;
        const int MAX_CONNECTION = 10;
        const int PORT_NUMBER = 30000;

        private int _connectionCount = 0;

        public int ConnectionCount
        {
            get { return _connectionCount; }
            set { _connectionCount = value; }
        }

        private TcpListener listener;
        Thread acceptThread = null;

        Stream stream = null;
        StreamReader reader = null;
        StreamWriter writer = null;
#endregion
        
        public void start()
        {
            // create thread, TCP socket, waiting connection coming
            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");
            listener = new TcpListener(ipAddress, PORT_NUMBER);
            listener.Start();

            // loop for accept connections
            try
            {
                acceptThread = new Thread((obj) => { AcceptConnection(); });
                acceptThread.Start();
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }

        public void stop()
        {
            // stop all thread
            if (acceptThread != null)
            {
                acceptThread.Abort();
            }
        }

        private void AcceptConnection()
        {
            while (_connectionCount < MAX_CONNECTION || MAX_CONNECTION == 0)
            {
                try
                {
                    Socket socket = listener.AcceptSocket();
                    _connectionCount++;

                    Thread t = new Thread((obj) =>
                    {
                        DoWork((Socket)obj);
                    }
                        );
                    t.Start(socket);
                }
                catch (System.Exception ex)
                {
                    throw ex;
                }
            }
        }

        private void DoWork(Socket socket)
        {
            try
            {
                clientCtrl = new ClientController();
                // insert client to database
                ClientDTO info = new ClientDTO();
                IPEndPoint ipEnd = (IPEndPoint)socket.RemoteEndPoint;
                info.Ip = ipEnd.Address.ToString();
                info.SharePort = ipEnd.Port.ToString();


                reader = new StreamReader(stream);
                writer = new StreamWriter(stream);
                writer.AutoFlush = true;
            }
            catch (System.Exception ex)
            {
            	throw ex;
            }
        
            // infinity loop for working
            while (true)
            {
                // receive command from client
                string cmd = reader.ReadLine();
                if (string.IsNullOrEmpty(cmd) || cmd.Equals(ACNetMessage.DISCONNECT))
                {
                    break; // exit loop and disconnect
                }

                // processing
                switch (cmd)
                {
                    case ACNetMessage.SHARE:
                        break;
                    case ACNetMessage.UNSHARED:
                        break;
                    case ACNetMessage.NAME_SEARCH:
                        break;
                    case ACNetMessage.MUSICIAN_SEARCH:
                        break;
                    case ACNetMessage.SINGER_SEARCH:
                        break;
                }
            }

            // disconnect and execute garbage collection
            try
            {
                if(stream != null)
                    stream.Close();
                ConnectionCount--;
                socket.Close();
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }

    }
}
